﻿#pragma once
#include "AsBasicGlobal.h"
#include "AsDefine.h"
#include <set>
#include <list>
#include <map>

AS_MEMBER_CLASS_DECLARATION(AsDebug);

__AS_JY(Update Infos
	2025.5.6 优化AsDebug输出顺序
)
class AS_BASIC_EXPORT AsDebug {
public:
	enum Flag {
		None = 0x00,
		LineFeed = 0x01,
		InsertSpace = 0x02,
		Lock = 0x04,
		Pause = 0x08,
		Default = LineFeed | InsertSpace | Lock,
	};
	enum EncodingFormat {
		GBK,
		Unicode,
		EncodingFormat_Default = GBK
	};

public:
	static void InstallDebugOutputConsole();
	static void UnInstallDebugOutputConsole();
	static void setEncodingFormat(EncodingFormat encodingFormat);
	static void setOutputTitie(std::string outputTitle);
	static void setEnableOutputTime(bool isEnable);
	static void setEnableWriteLog(std::string filename = "asdebug_log", bool appendTime = false);

public:
	static void printf(const char* fmt, ...);
	static void pause();

public:
	AsDebug(unsigned int flags = Default);
	~AsDebug();

private:
	std::shared_ptr<AS_MEMBER_CLASS(AsDebug)> mp;

public:
	unsigned int flags() const;
	void setFlags(unsigned int flags);

public:
	AsDebug& operator<<(bool info);
	AsDebug& operator<<(char info);
	AsDebug& operator<<(unsigned char info);
	AsDebug& operator<<(short info);
	AsDebug& operator<<(unsigned short info);
	AsDebug& operator<<(int info);
	AsDebug& operator<<(unsigned int info);
	AsDebug& operator<<(long info);
	AsDebug& operator<<(unsigned long info);
	AsDebug& operator<<(long long info);
	AsDebug& operator<<(unsigned long long info);
	AsDebug& operator<<(float info);
	AsDebug& operator<<(double info);
	AsDebug& operator<<(long double info);
	AsDebug& operator<<(const char* info);
	AsDebug& operator<<(const std::string& info);

	AsDebug& operator<<(const cv::Point& info);
	AsDebug& operator<<(const cv::Point2f& info);
	AsDebug& operator<<(const cv::Point2d& info);
	AsDebug& operator<<(const cv::Point3f& info);
	AsDebug& operator<<(const cv::Point3d& info);
	AsDebug& operator<<(const cv::Rect& info);
	AsDebug& operator<<(const cv::Rect2f& info);
	AsDebug& operator<<(const cv::Rect2d& info);
	AsDebug& operator<<(const cv::Vec2i& info);
	AsDebug& operator<<(const cv::Vec2f& info);
	AsDebug& operator<<(const cv::Vec2d& info);
	AsDebug& operator<<(const cv::Vec3i& info);
	AsDebug& operator<<(const cv::Vec3f& info);
	AsDebug& operator<<(const cv::Vec3d& info);
	AsDebug& operator<<(const cv::Vec4i& info);
	AsDebug& operator<<(const cv::Vec4f& info);
	AsDebug& operator<<(const cv::Vec4d& info);
	AsDebug& operator<<(const cv::RotatedRect& info);
	AsDebug& operator<<(const cv::Mat& info);

	template <typename _Type1, typename _Type2>
	AsDebug& operator<<(const std::pair<_Type1, _Type2> info);
	template <typename _Type>
	AsDebug& operator<<(const std::vector<_Type>& info);
	template <typename _Type>
	AsDebug& operator<<(const std::list<_Type>& info);
	template <typename _Type>
	AsDebug& operator<<(const std::set<_Type>& info);
	template <typename _Type1, typename _Type2>
	AsDebug& operator<<(const std::map<_Type1, _Type2>& info);

};

template <typename _Type1, typename _Type2>
AsDebug& AsDebug::operator<<(const std::pair<_Type1, _Type2> info) {
	unsigned int _flags = flags();
	setFlags(None);
	*this << "std::pair(" << info.first << ", " << info.second << ")";
	setFlags(_flags);
	return *this;
}

template <typename _Type>
AsDebug& AsDebug::operator<<(const std::vector<_Type>& info) {
	unsigned int _flags = flags();
	setFlags(None);
	*this << "std::vector(";
	for (auto it = info.cbegin(); it != info.cend(); it++) {
		if (it != info.cbegin()) *this << ", ";
		*this << *it;
	}
	*this << ")";
	setFlags(_flags);
	return *this;
}

template <typename _Type>
AsDebug& AsDebug::operator<<(const std::list<_Type>& info) {
	unsigned int _flags = flags();
	setFlags(None);
	*this << "std::list(";
	for (auto it = info.cbegin(); it != info.cend(); it++) {
		if (it != info.cbegin()) *this << ", ";
		*this << *it;
	}
	*this << ")";
	setFlags(_flags);
	return *this;
}

template <typename _Type>
AsDebug& AsDebug::operator<<(const std::set<_Type>& info) {
	unsigned int _flags = flags();
	setFlags(None);
	*this << "std::set(";
	for (auto it = info.cbegin(); it != info.cend(); it++) {
		if (it != info.cbegin()) *this << ", ";
		*this << *it;
	}
	*this << ")";
	setFlags(_flags);
	return *this;
}

template <typename _Type1, typename _Type2>
AsDebug& AsDebug::operator<<(const std::map<_Type1, _Type2>& info) {
	unsigned int _flags = flags();
	setFlags(None);
	*this << "std::map(";
	for (auto it = info.cbegin(); it != info.cend(); it++) {
		if (it != info.cbegin()) *this << ", ";
		*this << "<" << it->first << ">" << it->second;
	}
	*this << ")";
	setFlags(_flags);
	return *this;
}